package mlp.game.applebucking;

import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import mlp.game.applebucking.Apple.Type;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.os.SystemClock;
import android.util.Log;
import android.view.MotionEvent;

import com.overkill.game.GameEngine;
import com.overkill.game.GameOptions;
import com.overkill.game.GameOverListener;
import com.overkill.game.RenderView;
import com.overkill.game.Sprite;

public class AppleBloomEngine extends GameEngine {

	public AppleBloomEngine(GameOptions options, GameOverListener gameOverListener, int targetFps){
		super(options, gameOverListener, targetFps);
	}

	public int MAX_APPLES = 7;
	
	public int ZAP_MODE_DURATION_MS = 5000;
	
	public float CHANCE_OF_ROTTEN_APPLE = 0.215f;
	public float CHANCE_OF_POWER_APPLE = 0.015f;
	
	public int GAME_RUN_TIME = 100;

	public static Random random = new Random();
	
	long gameStartTime;
	long gameTimeLeft;
	long gameEndTime;
	long gamePauseTime;
	
	long zapModeEndTime;
	
	int countdownLeft = 3;
	
	int SCORE_TOTAL_APPLES = 0;
	int SCORE_CAUGHT_APPLES = 0;
	int SCORE_MISSED_APPLES = 0;
	int SCORE_POINTS = 0;

	
	Paint scoreText = new Paint();
	Paint scoreBoardFill = new Paint();
	Paint scoreBoardStroke = new Paint();
	Paint pauseText = new Paint();
	
	Cart cart;
	Bitmap background;
	private List<Apple> apples = new LinkedList<Apple>();
	private RandomAppleGenerator rap = new RandomAppleGenerator(random, CHANCE_OF_ROTTEN_APPLE, CHANCE_OF_POWER_APPLE, MAX_APPLES, "HARD");
	
	@Override
	public void inizialize(Rect stage) {
		super.inizialize(stage);
						
		Apple.MOVEMENTSPEED_PX_MAX = (int) dip(9);
		Apple.MOVEMENTSPEED_PX_MIN = (int) dip(4);
			
		rap.setDifficulty(options.getString("difficulty", "HARD"));
		
		rap.setGoodAppleBasket(new Sprite[]{
				new Sprite(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.apple_1), 24, 1),
				new Sprite(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.apple_2), 24, 1),
				new Sprite(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.apple_3), 24, 1),
				new Sprite(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.apple_4), 24, 1)
		});
		
		rap.setRottenAppleBasket(new Sprite[]{
				new Sprite(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.muffin), 24, 1)
		});

		rap.setPowerAppleBasket(new Sprite[]{
				new Sprite(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.power), 24, 1)
		});

		
		cart = new Cart(new Sprite(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.cart), 24, 5, false));

		background = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.background);

		scoreText.setColor(Color.BLACK);
		scoreText.setTextAlign(Align.CENTER);
		scoreText.setTextSize(dip(14));
		Typeface celestia = Typeface.createFromAsset(getContext().getAssets(), RenderView.TYPEFACE_PATH);
		scoreText.setTypeface(celestia);
		scoreText.setAntiAlias(true);

		pauseText = new Paint(scoreText);
		pauseText.setTextSize(dip(36));
		scoreBoardFill.setColor(0xCCFFFFFF);
		scoreBoardFill.setStyle(Style.FILL);
		scoreBoardStroke.setColor(0xCCED3C95);
		scoreBoardStroke.setStyle(Style.STROKE);
		scoreBoardStroke.setStrokeWidth(5);
		
		zapModeEndTime = 0;
		
		// Find lower center position for cart
		cart.moveTo((stage.width() - cart.getSprite().getWidth()) / 2, 
				     stage.height() - cart.getSprite().getHeight());
		
		// Set cart hitbox
		cart.setRelativHitBox(new RectF(
									dip(41), 
									dip(51), 
									dip(95), 
									dip(55)
							));
		
		// Set game end time
		gameStartTime = SystemClock.elapsedRealtime() + countdownLeft * 1000;
		gameEndTime = gameStartTime + GAME_RUN_TIME * 1000;

		Log.i("AppleBloomEngine", "inizialized");
	}
	
	@Override
	public void update(long gameTime, int deltaTime) {
		super.update(gameTime, deltaTime);
		gameTimeLeft = (gameEndTime - gameTime) / 1000;
		if (gamePaused == true)
			return;
		// Countdown
		if (gameTime >= gameStartTime) {
			gameRunning = true;
		} else {
			countdownLeft = (int) ((gameStartTime - gameTime) / 1000);
		}
		if (gameRunning == false)
			return;

		if (gameTime >= gameEndTime) {
			if(apples.size() > 0){
				gameEndTime = gameTime;
				rap.setActive(false);
			} else {
				this.gameOver();
				return;
			}
		}
			
		if(gameTime > zapModeEndTime)
			cart.setZapMode(false);
		else
			cart.setZapMode(true);
		
		SCORE_TOTAL_APPLES = rap.generate(apples, stage.right, gameTime);
		
		List<Apple> applesToRemove = new LinkedList<Apple>();
		for (Apple a : apples) {
			a.update(gameTime);
			if (cart.isCaught(a)) {
				applesToRemove.add(a);
				if(a.getType() == Type.GOOD){
					if(cart.isZapMode())
						SCORE_CAUGHT_APPLES += 1;
					else
						SCORE_CAUGHT_APPLES += 2;
				}else if(a.getType() == Type.POWER){
					zapModeEndTime = gameTime + ZAP_MODE_DURATION_MS;
				}else{
					SCORE_MISSED_APPLES += 1;
				}
				continue;
			}
			if (a.getPosition().y > stage.bottom) {
				applesToRemove.add(a);
				if(a.getType() == Type.GOOD){
					SCORE_MISSED_APPLES += 1;
				}
				continue;
			}
		}
		
		apples.removeAll(applesToRemove);

		cart.update(gameTime);

	}
	
	@Override
	public void draw(Canvas canvas) {
		super.draw(canvas);
		
		// Draw Background
		drawBackground(canvas);
		// Draw Apples
		for (Apple a : apples) {
			a.draw(canvas);
		}
		// Draw Cart
		cart.draw(canvas);
		// Draw Score
		this.drawScore(canvas);
		// Draw Pause screen
		if (gamePaused == true) {
			int y = (int) (stage.height() / 2 - pauseText.getTextSize() / 2);
			canvas.drawText(getString(R.string.pause_pause),
					stage.width() / 2, y, pauseText);
			canvas.drawText(getString(R.string.pause_tabanywhere),
					stage.width() / 2, (y + pauseText.getTextSize() / 2), scoreText);
		}
		// Draw pre-game countdown
		if (gameRunning == false) {
			canvas.drawText(getString(R.string.start_in, countdownLeft),
										stage.width() / 2,
										stage.height() / 2 - scoreText.getTextSize() / 2,
										pauseText);

		}
	}

	private void drawBackground(Canvas canvas) {
		canvas.drawColor(0xFFB1E6EE);
		
		Rect src = new Rect(background.getWidth() - stage.width(), 0, background.getWidth(), stage.height());					
		canvas.drawBitmap(background, src, stage, null);
		
//		canvas.drawBitmap(background, -background.getWidth() + stage.width(), 0, backgroundHue);
	}

	private void drawScore(Canvas canvas) {
		RectF scoreRectF = new RectF(0, -25, stage.right, (float) (scoreText.getTextSize() * 2.4));
		canvas.drawRoundRect(scoreRectF, 20, 20, scoreBoardFill);
		canvas.drawRoundRect(scoreRectF, 20, 20, scoreBoardStroke);
		canvas.drawText(getString(R.string.game_score, SCORE_CAUGHT_APPLES, SCORE_MISSED_APPLES), 
							stage.width() / 2,
							scoreText.getTextSize(), scoreText);
		canvas.drawText(getString(R.string.time_left, gameTimeLeft),
							stage.width() / 2,
							(float) (scoreText.getTextSize() * 2.05), scoreText);
	}
	
	@Override
	public void gameOver() {
		rap.report();
		GameOptions options = new GameOptions();
		options.put("SCORE_TOTAL_APPLES", SCORE_TOTAL_APPLES);
		options.put("SCORE_CAUGHT_APPLES", SCORE_CAUGHT_APPLES);
		options.put("SCORE_MISSED_APPLES", SCORE_MISSED_APPLES);
		super.gameOver(options);
	}
	
	@Override
	public void pauseGame() {
		gamePauseTime = SystemClock.elapsedRealtime();
		gamePaused = true;
		renderView.pauseRender(true);
	}
	
	@Override
	public void resumeGame() {
		long timeDiff = SystemClock.elapsedRealtime() - gamePauseTime;
		gameEndTime += timeDiff;
		gamePaused = false;
		renderView.resumeRender();
	}
	
	@Override
	public void handleTouchEvent(int action, float x, float y){	
		if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE) {
			if (gamePaused)
				resumeGame();

			cart.moveX((int) x - cart.getSprite().getWidth() / 2);
		}
	}
	
}
